package us.wili.dev.netty.jwt;

import io.jsonwebtoken.*;
import org.apache.commons.codec.digest.DigestUtils;
import us.wili.dev.common.util.snowflake.SnowflakeUtil;
import us.wili.dev.exception.ErrorCode;
import us.wili.dev.exception.JwtException;
import us.wili.dev.jwt.JwtUserException;
import us.wili.dev.jwt.model.ChannelEnum;
import us.wili.dev.jwt.model.IUser;
import us.wili.dev.jwt.util.JWTHelper;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;


public class JwtUtil extends JWTHelper {

    private SnowflakeUtil idWorker;

    public JwtUtil(SnowflakeUtil idWorker, String priKeyPath, String pubKeyPath) {
        super(priKeyPath, pubKeyPath);
        this.idWorker = idWorker;
    }

    @Override
    public IUser getAnonymousInfo() {
        JwtUser jwtInfo = new JwtUser();
        // 会话信息
        jwtInfo.setUuid(String.valueOf(idWorker.nextId()));
        jwtInfo.setAnonymous(true);

        return jwtInfo;
    }

    @Override
    public IUser getAnonymousInfo(Integer channel) {
        JwtUser jwtInfo = new JwtUser();
        // 会话信息
        jwtInfo.setUuid(String.valueOf(idWorker.nextId()));
        jwtInfo.setChannel(channel);
        jwtInfo.setAnonymous(true);

        return jwtInfo;
    }

    @Override
    public IUser getAnonymousInfo(ChannelEnum channelEnum) {
        return getAnonymousInfo(channelEnum.getCode());
    }

    @Override
    public String generateToken(IUser iUser, int expire) {
        if (!(iUser instanceof JwtUser)) {
            throw new JwtException(ErrorCode.JWT_ILLEGAL_USER);
        }

        JwtUser jwtUser = (JwtUser) iUser;
        if (!jwtUser.getAnonymous()) {
            if (jwtUser.getUserId() == null) {
                throw new JwtException(ErrorCode.JWT_USERID_IS_NULL);
            }
        } else {
            if (jwtUser.getUuid() == null) {
                throw new JwtException(ErrorCode.JWT_UUID_IS_NULL);
            }
        }

        ChannelEnum channelEnum = ChannelEnum.get(jwtUser.getChannel());
        if (channelEnum == null) {
            throw new JwtUserException("渠道类型不正确");
        }

        // 有效期
        LocalDateTime now = LocalDateTime.now().plusSeconds(expire);
        JwtBuilder jwtBuilder = Jwts.builder().setHeaderParam("typ", "JWT")
                .setExpiration(Date.from(now.atZone(ZoneId.systemDefault()).toInstant()));

        // 会话信息
        jwtBuilder.claim(JwtUser.IS_ANONYMOUS_KEY, jwtUser.getAnonymous());
        jwtBuilder.claim(JwtUser.CHANNEL_KEY, channelEnum.getCode());
        jwtBuilder.claim(JwtUser.UUID_KEY, jwtUser.getUuid());
        jwtBuilder.setId(jwtUser.getId());
        jwtBuilder.setSubject(jwtUser.getId());

        if (!jwtUser.getAnonymous()) {
            // 设置用户信息，set
        }

        // 压缩
        return jwtBuilder.signWith(SignatureAlgorithm.RS256, getPrivateKey()).compact();
    }

    @Override
    public IUser getInfoFromToken(String token) {
        Jws<Claims> claimsJws = parserToken(token);
        Claims body = claimsJws.getBody();
        long expiredSeconds = body.getExpiration().getTime() - System.currentTimeMillis();

        JwtUser jwtUser = new JwtUser();
        jwtUser.setExpiredSeconds(expiredSeconds);

        // 会话信息
        jwtUser.setAnonymous(objectToBoolean(body.get(JwtUser.IS_ANONYMOUS_KEY)));
        jwtUser.setUuid(objectToString(body.get(JwtUser.UUID_KEY)));
        jwtUser.setChannel(objectToInteger(body.get(JwtUser.CHANNEL_KEY)));

        // 解析获取用户信息
        // .set(.get());

        return jwtUser;
    }

    @Override
    public String refreshToken(String token, int expire) {
        JwtUser jwtInfo = (JwtUser) getInfoFromToken(token);
        return generateToken(jwtInfo, expire);
    }

    public String encrypt(String plain, String salt) {
        return DigestUtils.sha512Hex(salt + plain);
    }

    public boolean checkPwd(String checked, String plain, String salt) {
        return checked.equals(encrypt(plain, salt));
    }
}
